/*
REWRITTEN BY XINEF
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "gundrak.h"

enum eSpells
{
	SPELL_SUMMON_PHANTOM					= 55205,
	SPELL_SUMMON_PHANTOM_TRANSFORM			= 55097,
    SPELL_DETERMINED_STAB					= 55104,
    SPELL_DETERMINED_GORE					= 55102,
    SPELL_GROUND_TREMOR						= 55142,
    SPELL_QUAKE								= 55101,
    SPELL_NUMBING_SHOUT						= 55106,
    SPELL_NUMBING_ROAR						= 55100,
    SPELL_MOJO_FRENZY						= 55163,
    SPELL_TRANSFORMATION					= 55098
};

enum eSays
{
    SAY_AGGRO                               = 0,
    SAY_SLAY                                = 1,
    SAY_DEATH                               = 2,
    SAY_TRANSFORM                           = 3,
    SAY_QUAKE                               = 4,
    EMOTE_TRANSFORM                         = 5,
	EMOTE_TRANSFORMED						= 6,
	EMOTE_ALTAR								= 7
};

enum Events
{
	EVENT_GROUND_TREMOR						= 1,
	EVENT_NUMBLING_SHOUT					= 2,
	EVENT_DETERMINED_STAB					= 3,
	EVENT_TRANSFORMATION					= 4,
	EVENT_KILL_TALK							= 5,

	EVENT_PHANTOM							= 10
};

class boss_moorabi : public CreatureScript
{
	public:
		boss_moorabi() : CreatureScript("boss_moorabi") { }

		CreatureAI* GetAI(Creature* creature) const
		{
			return GetInstanceAI<boss_moorabiAI>(creature);
		}

		struct boss_moorabiAI : public BossAI
		{
			boss_moorabiAI(Creature* creature) : BossAI(creature, DATA_MOORABI)
			{
			}

			EventMap events2;

			void Reset()
			{
				BossAI::Reset();
				events2.Reset();
				events2.ScheduleEvent(EVENT_PHANTOM, 21000);
			}

			void EnterCombat(Unit* who)
			{
				Talk(SAY_AGGRO);
				BossAI::EnterCombat(who);
				me->CastSpell(me, SPELL_MOJO_FRENZY, true);

				events.ScheduleEvent(EVENT_GROUND_TREMOR, 18000);
				events.ScheduleEvent(EVENT_NUMBLING_SHOUT, 10000);
				events.ScheduleEvent(EVENT_DETERMINED_STAB, 20000);
				events.ScheduleEvent(EVENT_TRANSFORMATION, 12000);
			}

			void SpellHitTarget(Unit* caster, const SpellInfo* spellInfo)
			{
				if (spellInfo->Id == SPELL_TRANSFORMATION)
				{
					me->RemoveAurasDueToSpell(SPELL_MOJO_FRENZY);
					events.CancelEvent(EVENT_TRANSFORMATION);
					Talk(EMOTE_TRANSFORMED);
				}
			}

			void JustDied(Unit* killer)
			{
				Talk(SAY_DEATH);
				Talk(EMOTE_ALTAR);
				BossAI::JustDied(killer);
			}

			void KilledUnit(Unit*)
			{
				if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
				{
					Talk(SAY_SLAY);
					events.ScheduleEvent(EVENT_KILL_TALK, 6000);
				}
			}

			void UpdateAI(uint32 diff)
			{
				if (!me->IsInCombat())
				{
					events2.Update(diff);
					if (events2.ExecuteEvent() == EVENT_PHANTOM)
					{
						me->CastSpell(me, SPELL_SUMMON_PHANTOM, true);
						events2.ScheduleEvent(EVENT_PHANTOM, urand(20000, 25000));
					}
				}

				if (!UpdateVictim())
				return;

				events.Update(diff);
				if (me->HasUnitState(UNIT_STATE_CASTING))
					return;

				switch (events.ExecuteEvent())
				{
					case EVENT_GROUND_TREMOR:
						if (roll_chance_i(50))
							Talk(SAY_QUAKE);
						me->CastSpell(me, me->GetDisplayId() != me->GetNativeDisplayId() ? SPELL_QUAKE : SPELL_GROUND_TREMOR, false);
						events.ScheduleEvent(EVENT_GROUND_TREMOR, 10000);
						break;
					case EVENT_NUMBLING_SHOUT:
						me->CastSpell(me, me->GetDisplayId() != me->GetNativeDisplayId() ? SPELL_NUMBING_ROAR : SPELL_NUMBING_SHOUT, false);
						events.ScheduleEvent(EVENT_NUMBLING_SHOUT, 10000);
						break;
					case EVENT_DETERMINED_STAB:
						me->CastSpell(me->GetVictim(), me->GetDisplayId() != me->GetNativeDisplayId() ? SPELL_DETERMINED_GORE : SPELL_DETERMINED_STAB, false);
						events.ScheduleEvent(EVENT_DETERMINED_STAB, 8000);
						break;
					case EVENT_TRANSFORMATION:
						Talk(EMOTE_TRANSFORM);
						Talk(SAY_TRANSFORM);
						me->CastSpell(me, SPELL_TRANSFORMATION, false);
						me->CastSpell(me,SPELL_SUMMON_PHANTOM_TRANSFORM, true);
						events.ScheduleEvent(EVENT_TRANSFORMATION, 10000);
						break;
				}

				DoMeleeAttackIfReady();
			}
		};
};

class spell_moorabi_mojo_frenzy : public SpellScriptLoader
{
    public:
        spell_moorabi_mojo_frenzy() : SpellScriptLoader("spell_moorabi_mojo_frenzy") { }

        class spell_moorabi_mojo_frenzy_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_moorabi_mojo_frenzy_AuraScript);

            void HandlePeriodic(AuraEffect const* aurEff)
            {
                PreventDefaultAction();
				
				if (GetUnitOwner()->GetMap()->IsHeroic())
					GetUnitOwner()->SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f * (GetUnitOwner()->GetHealthPct()*GetUnitOwner()->GetHealthPct()/10000.0f));
				else
					GetUnitOwner()->SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f * (GetUnitOwner()->GetHealthPct()/100.0f));
            }

            void Register()
            {
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_moorabi_mojo_frenzy_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
            }
        };

        AuraScript* GetAuraScript() const
        {
            return new spell_moorabi_mojo_frenzy_AuraScript();
        }
};

class achievement_less_rabi : public AchievementCriteriaScript
{
    public:
        achievement_less_rabi() : AchievementCriteriaScript("achievement_less_rabi")
        {
        }

        bool OnCheck(Player* /*player*/, Unit* target)
        {
            return target && target->GetDisplayId() == target->GetNativeDisplayId();
        }
};

void AddSC_boss_moorabi()
{
    new boss_moorabi();
	new spell_moorabi_mojo_frenzy();
	new achievement_less_rabi();
}
